﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.Collections;

namespace Dare.Utilities
{
    /// <summary>
    /// 反射操作辅助类
    /// </summary>
    public sealed class ReflectionUtil
    {
        private ReflectionUtil()
        {
        }

        private static BindingFlags bindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Public |
                                                   BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;

        /// <summary>
        /// 执行某个方法
        /// </summary>
        /// <param name="obj">指定的对象</param>
        /// <param name="methodName">对象方法名称</param>
        /// <param name="args">参数</param>
        /// <returns></returns>
        public static object InvokeMethod(object obj, string methodName, object[] args)
        {
            object objResult = null;
            Type type = obj.GetType();
            objResult = type.InvokeMember(methodName, bindingFlags | BindingFlags.InvokeMethod, null, obj, args);
            return objResult;
        }

        /// <summary>
        /// 设置对象字段的值
        /// </summary>
        public static void SetField(object obj, string name, object value)
        {
            FieldInfo fieldInfo = obj.GetType().GetField(name, bindingFlags);
            object objValue = Convert.ChangeType(value, fieldInfo.FieldType);
            fieldInfo.SetValue(objValue, value);
        }

        /// <summary>
        /// 获取对象字段的值
        /// </summary>
        public static object GetField(object obj, string name)
        {
            FieldInfo fieldInfo = obj.GetType().GetField(name, bindingFlags);
            return fieldInfo.GetValue(obj);
        }

        /// <summary>
        /// 设置对象属性的值
        /// </summary>
        public static void SetProperty(object obj, string name, object value)
        {
            PropertyInfo propertyInfo = obj.GetType().GetProperty(name, bindingFlags);
            object objValue = Convert.ChangeType(value, propertyInfo.PropertyType);
            propertyInfo.SetValue(obj, objValue, null);
        }

        /// <summary>
        /// 获取对象属性的值
        /// </summary>
        public static object GetProperty(object obj, string name)
        {
            PropertyInfo propertyInfo = obj.GetType().GetProperty(name, bindingFlags);
            return propertyInfo.GetValue(obj, null);
        }

        public static string GetPropertiesString(object obj)
        {
            return GetPropertiesString(obj, ":", Environment.NewLine);
        }

        /// <summary>
        /// 获取对象属性信息（组装成字符串输出）
        /// </summary>
        public static string GetPropertiesString(object obj, string colSeparator, string rowSeparator)
        {
            if (obj == null) return String.Empty;
            PropertyInfo[] propertyInfos = obj.GetType().GetProperties(bindingFlags);
            StringBuilder strBuilder = new StringBuilder(propertyInfos.Length * 100);

            foreach (PropertyInfo property in propertyInfos)
            {
                if (property.CanRead)
                {
                    strBuilder.Append(property.Name);
                    strBuilder.Append(colSeparator);
                    try
                    {
                        object val = property.GetValue(obj, null);
                        if (val is ICollection)
                        {
                            foreach (object v in (val as ICollection))
                            {
                                strBuilder.Append(v).Append(",");
                            }
                            if (strBuilder[strBuilder.Length - 1] == ',') strBuilder.Remove(strBuilder.Length - 1, 1);
                        }
                        else if (val is IDictionary)
                        {
                            IDictionary dict = val as IDictionary;
                            foreach (object key in dict.Keys)
                            {
                                strBuilder.Append(key).Append("=").Append(dict[key]).Append(",");
                            }
                            if (strBuilder[strBuilder.Length - 1] == ',') strBuilder.Remove(strBuilder.Length - 1, 1);
                        }
                        else
                        {
                            strBuilder.Append(val);
                        }
                    }
                    catch (Exception ex)
                    {
                        strBuilder.Append("读取值失败:" + ex.Message);
                    }
                    strBuilder.Append(rowSeparator);
                }
            }

            return strBuilder.ToString();
        }

        /// <summary>
        /// 获取对象字段信息（组装成字符串输出）
        /// </summary>
        public static string GetFieldsString(object obj, string colSeparator, string rowSeparator)
        {
            if (obj == null) return String.Empty;
            FieldInfo[] fieldInfos = obj.GetType().GetFields(bindingFlags);
            StringBuilder strBuilder = new StringBuilder(fieldInfos.Length * 100);

            foreach (FieldInfo field in fieldInfos)
            {
                strBuilder.Append(field.Name);
                strBuilder.Append(colSeparator);
                try
                {
                    strBuilder.Append(field.GetValue(obj));
                }
                catch (Exception ex)
                {
                    strBuilder.Append("读取值失败:" + ex.Message);
                }
                strBuilder.Append(rowSeparator);
            }

            return strBuilder.ToString();
        }


        /// <summary>
        /// 获取公共静态字段
        /// </summary>
        public static T GetPublicStaticField<T>(string assemblyName, string className, string propertyName)
            where T : class
        {
            return Assembly.Load(assemblyName).GetType(className).InvokeMember(
                propertyName,
                BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField,
                null, null, null) as T;
        }

        /// <summary>
        /// 获取公共静态字段
        /// </summary>
        public static T GetPublicStaticFieldFrom<T>(string assemblyFile, string className, string propertyName)
            where T : class
        {
            return Assembly.LoadFrom(assemblyFile).GetType(className).InvokeMember(
                propertyName,
                BindingFlags.Public | BindingFlags.Static | BindingFlags.GetField,
                null, null, null) as T;
        }

        public static Assembly GetAssemblyFrom(string assemblyFile)
        {
            try
            {
                return Assembly.LoadFrom(assemblyFile);
            }
            catch
            {
                return null;
            }
        }


        public static T GetClassFrom<T>(string assemblyFile, string className)
            where T : class
        {
            Assembly assembly = GetAssemblyFrom(assemblyFile);
            if (assembly == null) return null;
            try
            {
                return assembly.CreateInstance(className) as T;
            }
            catch
            {
                return null;
            }
        }

        public static T[] CreateInstance<T>(string assemblyFile, params object[] args)
    where T : class
        {
            Assembly assembly = GetAssemblyFrom(assemblyFile);
            if (assembly == null) return null;
            List<T> listOjbs = new List<T>();
            Type[] types = assembly.GetExportedTypes();
            Type matchType = typeof(T);
            foreach (Type type in types)
            {
                if (type.IsClass && !type.IsAbstract && (matchType.IsAssignableFrom(type) || type == matchType))
                {
                    listOjbs.Add(Activator.CreateInstance(type, args) as T);
                }
            }
            return listOjbs.ToArray();
        }

        #region 使用反射,调用父窗体的事件
        /// <summary>
        /// 使用反射,调用父窗体的事件
        /// </summary>
        /// <param name="frm"></param>
        /// <param name="methodName"></param>
        /// <param name="args"></param>
        public static void InvokeMethod(Form frm, string methodName, object[] args)
        {
            Type t = frm.GetType();
            BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;

            MethodInfo m = t.GetMethod(methodName, flags);
            if (m != null)
            {
                m.Invoke(frm, args);
            }
        }
        #endregion 使用反射,调用父窗体的事件
    }
}
